package cn.yanji.service.impl;

import cn.hutool.core.io.resource.ResourceUtil;
import cn.yanji.service.DriverService;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.springframework.stereotype.Service;

import java.io.FileNotFoundException;
import java.net.URL;
import java.util.*;

/**
 * @author yanji w2c17lin@qq.com
 * @since 2018/11/6 下午 05:12
 */
@Service
public class DriverServiceImpl implements DriverService {

	@Override
	public ChromeBuilder chromeBuilder() {
		return new ChromeBuilder();
	}

	@Override
	public FirefoxBuilder firefoxBuilder() {
		return new FirefoxBuilder();
	}

	public static class ChromeBuilder {
		private static final String WEBDRIVER_CHROME_DRIVER = "webdriver.chrome.driver";

		private static final String CHROMEDRIVER_WINDOWS = "chromedriver.exe";
		private static final String CHROMEDRIVER_LINUX = "chromedriver";

		private List<String> arguments = new ArrayList<>();
		private Map<String, Object> device;

		ChromeBuilder() {
		}

		public ChromeBuilder argument(String argument) {
			this.arguments.add(argument);
			return this;
		}

		public ChromeBuilder headless() {
			return this.argument("--headless");
		}

		public ChromeBuilder devtools() {
			return this.argument("auto-open-devtools-for-tabs=true");
		}

		public ChromeBuilder wechat() {
			return this.device(375, 812, 3.0, "Mozilla/5.0 (Linux; Android 5.0; SM-N9100 Build/LRX21V) > " +
					"AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 > Chrome/37.0.0.0 Mobile Safari/537.36 > MicroMessenger/6.0.2.56_r958800.520 NetType/WIFI");
		}

		public ChromeBuilder device(int width, int height, double pixelRatio, String userAgent) {
			Map<String, Object> deviceMetrics = new HashMap<>();
			deviceMetrics.put("width", width);
			deviceMetrics.put("height", height);
			deviceMetrics.put("pixelRatio", pixelRatio);
			Map<String, Object> mobileEmulation = new HashMap<>();
			mobileEmulation.put("deviceMetrics", deviceMetrics);
			mobileEmulation.put("userAgent", userAgent);
			this.device = mobileEmulation;
			return this;
		}

		public WebDriver linux() throws FileNotFoundException {
			return build(CHROMEDRIVER_LINUX);
		}

		public WebDriver windows() throws FileNotFoundException {
			return build(CHROMEDRIVER_WINDOWS);
		}

		public WebDriver build(String driver) throws FileNotFoundException {
			URL driverPath = ResourceUtil.getResource(driver);
			if (Objects.isNull(driverPath)) {
				throw new FileNotFoundException("\"chromedriver\" not find, put \"chromedriver\" to project resources dir");
			}
			System.setProperty(WEBDRIVER_CHROME_DRIVER, driverPath.getPath());

			ChromeOptions chromeOptions = new ChromeOptions();
			chromeOptions.addArguments(arguments);
			Optional.ofNullable(device).ifPresent(value -> chromeOptions.setExperimentalOption("mobileEmulation", value));
			return new ChromeDriver(chromeOptions);
		}
	}

	public static class FirefoxBuilder {
		private static final String WEBDRIVER_GECKO_DRIVER = "webdriver.gecko.driver";
		private static final String GECKODRIVER = "geckodriver.exe";

		private List<String> arguments = new ArrayList<>();

		FirefoxBuilder() {
		}

		public FirefoxBuilder argument(String argument) {
			this.arguments.add(argument);
			return this;
		}

		public FirefoxBuilder headless() {
			return this.argument("--headless");
		}

		public WebDriver build() throws FileNotFoundException {
			URL driverPath = ResourceUtil.getResource(GECKODRIVER);
			if (Objects.isNull(driverPath)) {
				throw new FileNotFoundException("\"geckodriver.exe\" not find, put \"geckodriver.exe\" to project resources dir");
			}
			System.setProperty(WEBDRIVER_GECKO_DRIVER, driverPath.getPath());

			FirefoxOptions firefoxOptions = new FirefoxOptions();
			firefoxOptions.addArguments(arguments);
			return new FirefoxDriver(firefoxOptions);
		}

	}

}
